import wx
import math
from log_object import *

def makeNew(parent, window, param1):
    """ this is how we instantiate the device object from
        the main program that loads this plugin """
    return DistanceGraph(parent, window, param1)

class DistanceGraph:
	def __init__(self, parent, window, param1):
		self.parent = parent
		self.window = window

		self.type = DISTANCEGRAPH 
		self.param1 = param1
		self.param2 = NOT_DEFINED 

	def draw(self, dc, start, end, dim, space):
		active_gap =  self.parent.activeTime
		log_date = ""

		foreground = self.parent.getForegroundColor()
		background = self.parent.getBackgroundColor()

		dc.SetBrush(wx.TRANSPARENT_BRUSH)
		dc.SetPen(wx.Pen(foreground, 1))
		dc.SetTextBackground(background)
		dc.SetTextForeground(foreground)
		font = wx.Font(15, wx.TELETYPE, wx.NORMAL, wx.BOLD)
		dc.SetFont(font)

		base_unit = 10
		window_width = int(self.window.Width / space[0])
		window_height = int(self.window.Height / space[1])

		# 1. draw vertical and horizontal line
		x = (dim[0] * window_width) + 30
		origin_x = x
		y = (dim[1] * window_height) + window_height -61
		dc.DrawLines(((x, dim[1] * window_height), (x, y)))
		right_gap = 50
		graph_width = window_width - right_gap 
		endx = (dim[0] * window_width) + graph_width 
		dc.DrawText("time (unit: min.) ->", window_width - 190, y+30)

		# ????
                for current_log in self.parent.log_list :
                        if end == -1 or end > current_log.duration:
                                end = current_log.duration
                        log_date = current_log.date

                        # adjust base_unit
                        base_unit = int((end - start) / 5.0)
                        tmp = (end - start) % 5
                        if tmp > 1 :
                                base_unit  += 1

		unit_x = (end - start) / (base_unit *1.0)
		if unit_x < 1 : 
			unit_x =1
		width_x = graph_width / unit_x
 		y_start = dim[1] * window_height 
		dc.DrawLines(((x, y), (endx+right_gap, y)))

		# draw ruler for x and y 
		dc.SetPen(wx.Pen(foreground, 1, style=wx.DOT))
		font = wx.Font(12, wx.TELETYPE, wx.NORMAL, wx.BOLD)
		dc.SetFont(font)
		unit_x = int(unit_x) 
		time_unit = start
		dc.DrawText(str(start), origin_x, y+10)
		for i in range(unit_x):
			time_unit += base_unit 
			if time_unit > end :
				tmp = base_unit - time_unit + end 
				x +=  (width_x * tmp / base_unit)
				dc.DrawLines(((x, 50), (x, y+5)))
				dc.DrawText(str(end), x-7, y+10)
				break
			x += width_x
			dc.DrawLines(((x,  y_start + 50), (x, y+5)))
			dc.DrawText(str(time_unit), x-7, y+10)
		width_x = width_x / (base_unit * 1.0) 

		# 2. create data 
		# (start, end, number, [user_index_list...]) ...
		users_data = [] 
		# 2.1. make first list from the first user 
		idx = 0
		for current_log in self.parent.log_list :
			for pointer in current_log.pointer_list: 
				if self.parent.isSelectedUser(pointer.name) == False:
					idx += 1
					continue
				if idx == 0 : 
					# 2.1. make first list from the first user 
					for active_slot in pointer.active_range : 
						new_slot = (active_slot[1], active_slot[2], 1, [idx])
						users_data.append(new_slot)
					#print "---------- user start.... (first ...) ", pointer.name
					#for user in users_data:  
					#	print user 
					#print "---------- user end....<-------------- "
				else : 
					# 2.2. update... list with other users
					for active_slot in pointer.active_range : 
						sub_idx = 0
						overlap = False
						overlap_start = -1 
						registered = False
						active_start = active_slot[1]
						active_end = active_slot[2]
						#print "trying to add....=> ", active_start, active_end
						adj_idx = 0
						max = len(users_data)
						#for user in users_data:  
						for sub_idx in range(max): 
							sub_idx = sub_idx + adj_idx
							user = users_data[sub_idx]

							if overlap == True: 
								# VALIFIED!!!
								overlap = False

							# it is from same user...., just skip
							u_list = user[3]
							found = False
							for u in u_list :
								if u == idx :
									found = True
									break
							if found == True:
								continue
 
							if active_start <= user[0]:
								if active_end <= user[0]:
									# new slot, VALIFIED!!
									new_slot = (active_start, active_end, 1, [idx])
									users_data.insert(sub_idx, new_slot)
									registered = True 
									#print "1)"
									break
								else:
									# add new
									if active_start < user[0] : 
										new_slot = (active_start, user[0], 1, [idx])
										users_data.insert(sub_idx, new_slot)
										sub_idx +=1 
										adj_idx += 1 
										#print " added) sub_idx=", sub_idx, new_slot
										#for temp_user in users_data:  
										#	print temp_user
										#print "----- added)"

									# need to modify
									if active_end < user[1] : 
										# VALIFIED!!!
										temp = []
										for u in u_list :  
											temp.append(u)
										temp.append(idx)

										new_slot = (user[0], active_end, user[2]+1, temp)
										l = users_data.pop(sub_idx)
										del l
										users_data.insert(sub_idx, new_slot)
									
										new_slot = (active_end, user[1], user[2], u_list)
										users_data.insert(sub_idx+1, new_slot)
										registered = True 

										del temp
										#print "2)"
										break
									elif active_end == user[1] : 
										# increase number
										temp = []
										for u in u_list :  
											temp.append(u)
										temp.append(idx)

										new_slot = (user[0], user[1], user[2]+1, temp)
										l = users_data.pop(sub_idx +1)
										del l
										users_data.insert(sub_idx, new_slot)
										registered = True 
										del temp
										#print "3)"
										break
									else :
										# VALIFIED!!!
										temp = []
										for u in u_list :  
											temp.append(u)
										temp.append(idx)

										new_slot = (user[0], user[1], user[2]+1, temp)
										l = users_data.pop(sub_idx)
										del l
										users_data.insert(sub_idx, new_slot)

										overlap = True
										#overlap_start = user[1]
										active_start = user[1]
										registered = True 
										del temp
										#print "4)"
										continue
							elif active_start <= user[1] :
								if active_end <= user[1]:
									# VALIDATED!!!! 
									temp = []
									for u in u_list :  
										temp.append(u)
									temp.append(idx)

									new_slot = (user[0], active_start, user[2], u_list)
									l = users_data.pop(sub_idx)
									del l
									users_data.insert(sub_idx, new_slot)

									new_slot = (active_start, active_end, user[2]+1, temp)
									users_data.insert(sub_idx+1, new_slot)

									if active_end < user[1]:
										new_slot = (active_end, user[1],  user[2], u_list)
										users_data.insert(sub_idx+2, new_slot)
									registered = True
									del temp
									#print "5)"
									break
								else:
									# VALIFIED!!!
									temp = []
									for u in u_list :  
										temp.append(u)
									temp.append(idx)

									new_slot = (user[0], active_start, user[2], u_list)
									l = users_data.pop(sub_idx)
									del l
									users_data.insert(sub_idx, new_slot)
	
									new_slot = (active_start, user[1], user[2]+1, temp)
									users_data.insert(sub_idx+1, new_slot)

									overlap = True
									active_start = user[1]
									adj_idx += 1 
									del temp

									#print "6)"
									registered = True
									continue

							if overlap == True:
								new_slot = (active_start, active_end, 1, [idx])
								users_data.insert(sub_idx, new_slot)
								#print "7)-", sub_idx, active_start, active_end
								break


						if registered == False or overlap == True: 
							# VALIFIED!!!
							new_slot = (active_start, active_end, 1, [idx])
							users_data.append(new_slot)
							#print "8)"

						#print "---------- user start.... ", pointer.name
						#for user in users_data:  
						#	print user 
						#print "---------- user end....<-------------- "
				idx += 1


		# hj
		# let draw users_data
		dc.SetPen(wx.Pen(foreground, 1))
		dc.SetBrush(wx.Brush(foreground))
		dc.DrawRectangle(origin_x, y-30, graph_width, 30)
		number = 1 
		for user in users_data : 
			number = user[2]
			color = 255 - (70 * number)
			dc.SetPen(wx.Pen(wx.Colour(0,color,0), 1))
			dc.SetBrush(wx.Brush(wx.Colour(0, color, 0)))

			active_start = user[0] / 60
			active_end = user[1] / 60
			# adjust start/end
			if active_start < start:
				if active_end < start:
					continue
				else :
					active_start = start 
			if active_end > end:
				active_end = end

			x1 =((active_start - start) * width_x) + origin_x 
			x2 =((active_end - start) * width_x) + origin_x 
			dc.DrawRectangle(x1, y-30, x2 - x1, 30)

		# start, end, number, list of user id	
		new_pnt_list = [] 
		temp = (0, 0, 0, 0, []) 
		new_pnt_list.append(temp)
		max_dis = -1
		max_x_dis = -1
		max_y_dis = -1
		for user in users_data : 
			if user[2] > 1 :
				u_list = user[3]
				active_start = user[0] 
				active_end = user[1] 
				overlapped_list = [] 
				for u in u_list:
					pointer = None 
					for current_log in self.parent.log_list :
						pointer = current_log.pointer_list[u]
						break
					if pointer != None :
						#print pointer.name, active_start, active_end
						l = pointer.getPosition(active_start, active_end)
						overlapped_list.append(l)


				# unit is second.... , 1 second based
				length_period = int((active_end - active_start) / 1.0)
				#print length_period, active_start, active_end
				t = active_start
				for i in range(length_period) : 
					p_list = []
					dis = 0 
					prev_x = -1
					prev_y = -1
					x_dis = 0 
					y_dis = 0 
					count = 0	
					for j in range(user[2]) : 
						temp = self._getPosition(t, overlapped_list[j]) 
						if temp == None: 
							print "error.... could not find position.....", t, j, overlapped_list[j]
							continue
						if prev_x != -1 : 
							a = ((temp[0] - prev_x) * (temp[0] - prev_x)) + ((temp[1] - prev_y) * (temp[1] - prev_y))
							dis += math.sqrt(a)
							x_dis += math.fabs(prev_x - temp[0]) 
							y_dis += math.fabs(prev_y - temp[1]) 
						count += 1
						prev_x = temp[0]
						prev_y = temp[1]
						p_list.append(temp)
					if count == user[2] : 
						dis /= count  
						x_dis /= count 
						y_dis /= count
						if dis > max_dis :
							max_dis = dis
						if x_dis > max_x_dis :
							max_x_dis = x_dis 
						if y_dis > max_y_dis :
							max_y_dis = y_dis 
						temp = (t, dis, x_dis, y_dis, p_list) 
						new_pnt_list.append(temp)
					else :
						print "error.... ---------> ", count, user[2]
					del p_list
					t += 1.0

				for temp in overlapped_list :
					del temp 
				del overlapped_list
			elif user[2] == 1 :
				temp = (user[0], 0, 0, 0, []) 
				new_pnt_list.append(temp)
				temp = (user[1], 0, 0, 0, []) 
				new_pnt_list.append(temp)
		temp = (end * 60, 0, 0, 0, []) 
		new_pnt_list.append(temp)

		# hj
		#print new_pnt_list
		#print max_dis

		# draw ave. distance
		prev_x = -1
		prev_y = -1
		y -= 50
		# temp....
		graph_height_1 = 150
		dc.SetPen(wx.Pen(foreground, 1))
		for pnt in new_pnt_list :
			pnt_min = pnt[0] / 60
			x1 =((pnt_min - start) * width_x) + origin_x 
			y1 = int((pnt[1]  * graph_height_1)  / max_dis)
			if x1 < origin_x : 
				prev_x =  origin_x 
				prev_y = y1
				continue
			#print x1, y1
			if prev_x != -1 :
				dc.DrawLines(((prev_x, y-prev_y), (x1, y- y1)))
			prev_x = x1
			prev_y = y1

		x = (dim[0] * window_width) + 30
		y -= graph_height_1 
		dc.DrawLines(((x, y+graph_height_1), (endx+right_gap, y+graph_height_1)))
		dc.SetPen(wx.Pen(foreground, 1, style=wx.DOT))
		dc.DrawLines(((x, y), (endx+right_gap, y)))
		dc.DrawText(str(int(max_dis)), x+5, y-15)
		dc.DrawText("average distance", x+5, y-30)

		# draw ave. y distance
		y -= 50
		prev_x = -1
		prev_y = -1
		dc.SetPen(wx.Pen(foreground, 1))
		for pnt in new_pnt_list :
			pnt_min = pnt[0] / 60
			x1 =((pnt_min - start) * width_x) + origin_x 
			y1 = int((pnt[3]  * graph_height_1)  / max_y_dis)
			if x1 < origin_x : 
				prev_x =  origin_x 
				prev_y = y1
				continue
			if prev_x != -1 :
				dc.DrawLines(((prev_x, y-prev_y), (x1, y- y1)))
			prev_x = x1
			prev_y = y1

		x = (dim[0] * window_width) + 30
		y -= graph_height_1 
		dc.DrawLines(((x, y+graph_height_1), (endx+right_gap, y+graph_height_1)))
		dc.SetPen(wx.Pen(foreground, 1, style=wx.DOT))
		dc.DrawLines(((x, y), (endx+right_gap, y)))
		dc.DrawText(str(int(max_y_dis)), x+5, y-15)
		dc.DrawText("average y distance", x+5, y-30)

		# draw ave. x distance
		y -= 50
		prev_x = -1
		prev_y = -1
		dc.SetPen(wx.Pen(foreground, 1))
		for pnt in new_pnt_list :
			pnt_min = pnt[0] / 60
			x1 =((pnt_min - start) * width_x) + origin_x 
			y1 = int((pnt[2]  * graph_height_1)  / max_x_dis)
			if x1 < origin_x : 
				prev_x =  origin_x 
				prev_y = y1
				continue
			if prev_x != -1 :
				dc.DrawLines(((prev_x, y-prev_y), (x1, y- y1)))
			prev_x = x1
			prev_y = y1

		x = (dim[0] * window_width) + 30
		y -= graph_height_1 
		dc.DrawLines(((x, y+graph_height_1), (endx+right_gap, y+graph_height_1)))
		dc.SetPen(wx.Pen(foreground, 1, style=wx.DOT))
		dc.DrawLines(((x, y), (endx+right_gap, y)))
		dc.DrawText(str(int(max_x_dis)), x+5, y-15)
		dc.DrawText("average x distance", x+5, y-30)

		for pnt in new_pnt_list :
			del pnt
		del new_pnt_list

		# clear memory
		for user in users_data : 
			del user
		del users_data


		font = wx.Font(12, wx.TELETYPE, wx.NORMAL, wx.BOLD)
		dc.SetFont(font)
		x = (dim[0] * window_width) + 30
		y = (dim[1] * window_height) + 10
		dc.DrawText(log_date, x+5, y)
		dc.DrawText("pointers' position", x+5, y + 15)

		x = (dim[0] * window_width) + window_width -200
		dc.DrawText("no. of active users:", x, y)
		max= len(self.parent.selected_user_list)
		y += 10
		for i in range(max):
			ith = i + 1
			color = 255 - (70 * (ith))
			dc.SetPen(wx.Pen(wx.Colour(0,color,0), 1))
			dc.SetBrush(wx.Brush(wx.Colour(0, color, 0)))
			dc.DrawRectangle(x + (30*i), y+5, 30, 20)
			dc.DrawText(str(ith), x + (30*i)+10, y+10)


	def _getPosition(self, t, overlapped_list):
		prev_l = None 
		for l in overlapped_list : 
			if l[0] == t :
				return (l[1], l[2])
			if l[0] > t :
				return (prev_l[1], prev_l[2])
			prev_l = l
		if prev_l == None : 
			return prev_l
		else :
			return (prev_l[1], prev_l[2])


